package main

import (
	"encoding/base64"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/tjfoc/gmsm/sm2"
	"net/http"
	"sort"
)

//================================================================================
type THyRequest struct {
	AppId        string `json:"app_id" form:"app_id" binding:"required"`
	Charset      string `json:"charset" form:"charset" binding:"required"`
	Method       string `json:"method" form:"method" binding:"required"`
	Version      string `json:"version" form:"version" binding:"required"`
	Format       string `json:"format" form:"format" binding:"required"` // 可能的值：hex, base64, plain 或者为空
	SignType     string `json:"sign_type" form:"sign_type" binding:"required"`
	Timestamp    string `json:"timestamp" form:"timestamp" binding:"required"`
	BizContent   string `json:"biz_content" form:"biz_content" `
	NotifyUrl    string `json:"notify_url" form:"notify_url" `
	AppAuthToken string `json:"app_auth_token" form:"app_auth_token" `
	//Sign         string `json:"sign" form:"sign"`
}
type THyResponse struct {
	Code       string `json:"code" form:"code" binding:"required"`
	Message    string `json:"msg" form:"msg" binding:"required"`
	SubCode    string `json:"sub_code" form:"sub_code" binding:"required"`
	SubMessage string `json:"sub_msg" form:"sub_msg" binding:"required"`
	Sign       string `json:"sign" form:"sign"`
}

func add_not_null_param_to_map(dict map[string]string, k, v string) {
	if len(v) > 0 {
		dict[k] = v
	}
}

func hy_request_to_sign_source(input *THyRequest) string {
	dict := make(map[string]string)
	add_not_null_param_to_map(dict, "app_id", input.AppId)
	add_not_null_param_to_map(dict, "charset", input.Charset)
	add_not_null_param_to_map(dict, "method", input.Method)
	add_not_null_param_to_map(dict, "version", input.Version)
	add_not_null_param_to_map(dict, "format", input.Format)
	add_not_null_param_to_map(dict, "sign_type", input.SignType)
	add_not_null_param_to_map(dict, "timestamp", input.Timestamp)
	add_not_null_param_to_map(dict, "biz_content", input.BizContent)
	add_not_null_param_to_map(dict, "notify_url", input.NotifyUrl)
	add_not_null_param_to_map(dict, "app_auth_token", input.AppAuthToken)

	var keys []string
	for k, _ := range dict {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	src := ""
	for _, k := range keys {
		if len(src) > 0 {
			src += "&"
		}
		src += k + "=" + dict[k]
	}
	return src
}
func hy_response_to_sign_source(input *THyResponse) string {
	dict := make(map[string]string)
	add_not_null_param_to_map(dict, "code", input.Code)
	add_not_null_param_to_map(dict, "msg", input.Message)
	add_not_null_param_to_map(dict, "sub_code", input.SubCode)
	add_not_null_param_to_map(dict, "sub_msg", input.SubMessage)

	var keys []string
	for k, _ := range dict {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	src := ""
	for _, k := range keys {
		if len(src) > 0 {
			src += "&"
		}
		src += k + "=" + dict[k]
	}
	return src
}

func hy_message_verify(c *gin.Context) {
	input := &THyResponse{}
	err := c.ShouldBind(input)
	if err != nil {
		Return_params_error_result(c, err)
		return
	}

	src := hy_response_to_sign_source(input)
	fmt.Printf("sign source: %s\n", src)

	sign, _ := base64.StdEncoding.DecodeString(input.Sign)
	bVerified := gHySm2PubKey.Verify([]byte(src), sign)

	Return_sign_verification_result(c, bVerified)
}

func hy_message_sign(c *gin.Context) {
	input := &THyRequest{}
	err := c.ShouldBind(input)
	if err != nil {
		Return_params_error_result(c, err)
		return
	}

	src := hy_request_to_sign_source(input)
	fmt.Printf("sign source: %s\n", src)

	r, s, err := sm2.Sm2Sign(gSm2PrivKey, []byte(src), nil, nil)
	if err != nil {
		Return_ok_result(c, "1000", "签名出错："+err.Error(), nil)
		return
	}

	var buf []byte
	buf = append(buf, r.Bytes()...)
	buf = append(buf, s.Bytes()...)

	v := &ReturnValue{
		Code:    "0000",
		Message: "",
		Format:  "base64",
	}
	v.Data = base64.StdEncoding.EncodeToString(buf)
	c.JSON(http.StatusOK, v)
}
